use std::fmt;
use std::fmt::Display;

macro_rules! status_codes {
    (
        $(
            $(#[$docs:meta])*
            ($num:expr, $field_name:ident, $phrase:expr);
        )+
    ) => {
        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
        pub enum StateCode {
        $(
            $(#[$docs])*
            $field_name = $num,
        )+

        }

        impl StateCode{
            pub fn message(&self) -> &'static str {
                match self {
                    $(
                    StateCode::$field_name => $phrase,
                    )+
                }
            }
        }
    }
}

status_codes! {
    /// -------------------系统状态码-------------------

    /// success (成功)
    (0,Success, "success");
    /// server inner error (服务器内部错误)
    (2,Error, "server inner error");
    /// client param format error (参数格式错误)
    (3,ParamError, "client param format error");
    /// client state is wrong (客户端请教的信息与预期的状态不一致)
    (4,ClientError, "client state is wrong");
    /// invalid operate (非法的请求)
    (5,InvalidOperate, "invalid operate");
    /// signature is error (签名不正确)
    (6,SignError, "signature is error");
    /// client param out of range (参数超出范围)
    (7,ParamOutOfRange, "client param out of range");
    /// config no exist (配置不存在)
    (8,ConfigNoExist, "config no exist");
    /// request time out (请求超时)
    (9,RequestTimeout, "request time out");
    /// server is invalid (服务不可用)
    (11,ServerInvalid, "server is invalid");
    /// repeated operate (重复的操作请求)
    (12,RepeatedOperate, "repeated operate");
    /// operate is too frequent (操作太过频繁)
    (13,OperateTooFrequent, "operate is too frequent");

    /// ----------User---------------------------

    /// user is not login (用户未登陆)
    (101,UserNotLogin, "user is not login");
    /// user is not exist (用户不存在)
    (102,UserNoExist, "user is no exist");
}

impl StateCode {
    /// 获取对应状态码
    pub fn code(&self) -> i32 {
        *self as i32
    }

    /// 是否是成功的状态码
    pub fn is_success(&self) -> bool {
        *self == StateCode::Success
    }
}

impl Display for StateCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl warp::reject::Reject for StateCode {}
